package core.models;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.AbstractList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import javax.swing.DefaultListModel;

import org.apache.commons.lang3.StringUtils;


public class NetInterfaces extends DefaultListModel {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4834534131492099400L;
	LinkedList<String> interfacesFileContents;
	private static final String AUTO_REGEX = "^\\s*(auto)\\s\\w{2,}(:\\d+)?\\s*$";
	private static final String IFACE_REGEX = "^\\s*(iface)\\s+\\w{2,}(:\\d+)?\\s+(inet)\\s+((static)|(loopback)|(dhcp))\\s*$";
	private static final String MNGRHEADER_REGEX = "^### ROUTER MANAGER GENERATED CONTENT ###$";
	private static final String MNGRHEADER = "### ROUTER MANAGER GENERATED CONTENT ###";

	// Loads interfaces from /etc/network/interfaces file
	public void loadInterfaces(File file) throws FileNotFoundException {
		interfacesFileContents = new LinkedList<String>();
		Scanner scanner = new Scanner(file);
		while (scanner.hasNextLine()) {
			String line = scanner.nextLine();
			if (line.matches(MNGRHEADER_REGEX))
				continue;
			if (line.matches(AUTO_REGEX)) {
				String[] autoContents = line.trim().split("\\s+");
				String next = scanner.nextLine();
				if (next.matches(IFACE_REGEX)) {
					String[] ifaceContents = next.trim().split("\\s+");
					if (autoContents[1].equals(ifaceContents[1]))
						processInterface(true, ifaceContents[1],
								ifaceContents[3], scanner);
				}
			} else if (line.matches(IFACE_REGEX)) {
				String[] ifaceContents = line.split("\\s+");
				processInterface(false, ifaceContents[1], ifaceContents[3],
						scanner);
			} else
				interfacesFileContents.add(line);
		}
	}

	// Generates and uploads new /etc/network/interfaces file
	public File generateInterfacesFile() throws IOException {
		File file = File.createTempFile("RtrMngrTmp",
				Long.toString(System.currentTimeMillis()));
		file.deleteOnExit();
		BufferedWriter out = new BufferedWriter(new FileWriter(file));

		// Other content
		for (String line : interfacesFileContents) {
			out.write(line);
			out.newLine();
		}

		// Headline
		out.write(MNGRHEADER);
		out.newLine();
		out.newLine();

		List<NetInterface> interfaces = new AbstractList<NetInterface>() {
			@Override
			public NetInterface get(int index) {
				return (NetInterface) getElementAt(index);
			}

			@Override
			public int size() {
				return getSize();
			}
		};

		for (NetInterface iface : interfaces) {
			writeInterface(iface, out);
		}
		out.close();
		return file;
	}

	private void writeInterface(NetInterface iface, BufferedWriter out)
			throws IOException {
		if (iface.isAuto()) {
			out.write("auto " + iface.getName());
			out.newLine();
		}
		out.write("iface " + iface.getName() + " inet " + iface.getType());
		out.newLine();
		if (iface.getType().equals("static")) {
			out.write("   address " + iface.getAddress());
			out.newLine();
			out.write("   netmask " + iface.getNetmask());
			out.newLine();

			String gateway = iface.getGateway();
			String broadcast = iface.getBroadcast();
			String network = iface.getNetwork();
			if (gateway != null) {
				out.write("   gateway " + gateway);
				out.newLine();
			}
			if (broadcast != null) {
				out.write("   broadcast " + broadcast);
				out.newLine();
			}
			if (network != null) {
				out.write("   network " + network);
				out.newLine();
			}
		}

		for (String s : iface.getUpList()) {
			out.write("   up " + s);
			out.newLine();
		}

		for (String s : iface.getDownList()) {
			out.write("   down " + s);
			out.newLine();
		}

		for (String s : iface.getPreUpList()) {
			out.write("   pre-up " + s);
			out.newLine();
		}

		for (String s : iface.getPreDownList()) {
			out.write("   pre-down " + s);
			out.newLine();
		}
		
		out.newLine();
	}

	private void processInterface(boolean auto, String name, String type,
			Scanner scanner) {
		NetInterface iface = new NetInterface();
		iface.setAuto(auto);
		iface.setName(name);
		iface.setType(type);
		while (scanner.hasNextLine()) {
			String[] contents = scanner.nextLine().trim().split("\\s+");
			// TODO Make sure that address, netmask, gateway, network and
			// broadcast are set max once.
			if (contents[0].equals("address"))
				iface.setAddress(contents[1]);
			else if (contents[0].equals("netmask"))
				iface.setNetmask(contents[1]);
			else if (contents[0].equals("gateway"))
				iface.setGateway(contents[1]);
			else if (contents[0].equals("network"))
				iface.setNetwork(contents[1]);
			else if (contents[0].equals("broadcast"))
				iface.setBroadcast(contents[1]);
			else if (contents[0].equals("up"))
				iface.getUpList().add(StringUtils.join(contents, " ", 1, contents.length));
			else if (contents[0].equals("down"))
				iface.getDownList().add(StringUtils.join(contents, " ", 1, contents.length));
			else if (contents[0].equals("pre-up"))
				iface.getPreUpList().add(StringUtils.join(contents, " ", 1, contents.length));
			else if (contents[0].equals("pre-down"))
				iface.getPreDownList().add(StringUtils.join(contents, " ", 1, contents.length));
			else
				break;
		}
		if (iface.isValid())
			this.addElement(iface);
	}
}
